import { useEffect, useRef, useState } from 'react';
import i18n from '@app-cad/common/utils/i18next';
import {
  BaseCommand,
  CommandDialog,
  pickedModelData,
  pickedVertexData,
  FeatureManager,
} from '@amcax/base';
import { docMgr } from '@app-base/module';
import { CommandLabeledItemWrapper } from '@app-cad/common/components/command-form/item-wrapper';
import CmdInteractor from '../cmd-interactor/CmdInteractor';
import {
  MultiPickInput,
  PickInputValueType,
} from '@app-base/common/components/pick-input/3d';
import { useCommand } from '@app-base/common/hooks/useCommand';
import { CommandFormFooter } from '@app-base/common/components/command-form/footer';
import { ComCommand } from '../cmd-interactor/component';
import { args, InitType } from './type';
import { defaultEventCenter } from '@app-base/common/events/DefaultEventCenter';
import { removePoint } from '../cmd-interactor/base';
import { antennaInfo } from '../importExport/data';
import { Vector3, Vector3Tuple } from 'three';
import { wsApi } from '@app-base/server';
import './index.scss';
import { useTools } from '@app-base/common/hooks/useTools';
let baseInfo: {
  x?: number;
  y?: number;
  z?: number;
  ox?: number;
  oy?: number;
  oz?: number;
} = {};
function PointAxis({ onClose, title, props }) {
  defaultEventCenter().setState('cmd-antenna-point');
  const { confirmCommand, clear, isLoading, isPreviewLoading } = useCommand(
    'cmd-antenna-point',
    {
      commandName: 'Translation',
      onClose,
      finishDraw: checkAndFinishDraw,
    },
  );
  const [param, setParam] = useState<InitType>(args);
  const cmdRef = useRef<CmdInteractor>(null);
  const [active, setActive] = useState<number>(2);
  useEffect(() => {
    cmdRef.current = new CmdInteractor({ setParam, setActive });
    cmdRef.current.addExit(onClose);
    return () => {
      cmdRef.current?.destroy();
      cmdRef.current = null;
    };
  }, []);
  const [picked, setPicked] = useState<pickedModelData>(null);
  const [pickedPoint, setPickedPoint] = useState<pickedVertexData>(null);
  const [pickedAxis, setPickedAxis] = useState<pickedModelData>(null);
  const [isExecuted, setIsExecuted] = useState<boolean>(false);
  const { picker } = useTools();

  useEffect(() => {
    if (props?.params) {
      const point = new Vector3(
        props.params.end[0],
        props.params.end[1],
        props.params.end[2],
      );
      setPicked(
        picker.generatePickObjByPickID(
          props?.dxid as string,
        ) as pickedModelData,
      );
      baseInfo = {
        x: props.params.end[0],
        y: props.params.end[1],
        z: props.params.end[2],
        ox: props.params.origin[0],
        oy: props.params.origin[1],
        oz: props.params.origin[2],
      };
      cmdRef.current.setFormKey('antPoint');
      cmdRef.current.setPointAndParam(point, '', '');
    }
  }, [props]);

  const onPick = (result) => {
    setPicked(result[0]);
    result[0] && setActive(1);
  };
  async function checkAndFinishDraw() {
    if (!isFormDataValid()) return;
    await executeFn(false);
    onClose();
  }
  const remove = () => {
    setParam((state) => ({
      ...state,
      antPoint: {
        name: '',
        entityId: '',
        point: null,
      },
    }));
    cmdRef.current.removeByFormKey('antPoint');
    removePoint();
  };
  useEffect(() => {
    cmdRef.current.isPick = active === 1;
    active !== 1 && cmdRef.current.removeAssistPoint();
  }, [active, param, picked]);
  const isFormDataValid = () => {
    const { id, antPoint } = getId(picked, param);
    if (!id || !antPoint) {
      setIsExecuted(false);
      return false;
    }
    setIsExecuted(true);
    return true;
  };
  const setCurrentBox = async (id: string) => {
    if (!FeatureManager.isFeatureEnabled('set-current-box')) {
      return;
    }
    const parent = docMgr.documentObjects.filter(
      (item) =>
        item.type === 'GeomBox' &&
        item?.children?.length > 0 &&
        item?.children?.find((e) => e.dxid === id),
    );
    if (parent && parent.length > 0) {
      await wsApi.execCmd({
        c: 'SetCurrentBox',
        o: parent[0].dxid,
      });
      docMgr.workingObjectDxid = parent[0].dxid;
    }
  };
  const executeFn = async (preview: boolean) => {
    const { id, antPoint, startPoint, originPoint } = getId(picked, param);
    const start = pickedPoint?.assisObj?.getVertex()?.toArray() || startPoint;
    const origin = pickedPoint?.assisObj?.getVertex()?.toArray() || originPoint;
    await setCurrentBox(id);
    return confirmCommand(
      {
        a: {
          mode: 'point',
          keepSrc: false,
          start,
          end: antPoint,
          origin,
        },
        o: id,
      },
      preview,
    );
  };
  const preview = async () => {
    clear();
    if (!isFormDataValid()) return;
    await executeFn(true);
  };
  useEffect(() => {
    preview();
  }, [param]);
  useEffect(() => {
    // 只有当props不存在时才从antennaInfo获取数据，避免覆盖props中设置的baseInfo
    if (!props?.params) {
      baseInfo = antennaInfo().getAntennaInfoById(picked?.idInfo?.o)?.args;
    }
  }, [picked, props?.params]);
  return (
    <CommandDialog
      title={title}
      onClose={onClose}
      className='antenna'
      style={{ width: '300px' }}
      placement='topLeft'>
      {/* 线 */}
      <div className='px_20 w_full'>
        <CommandLabeledItemWrapper label=''>
          <MultiPickInput
            active={active === 2}
            value={[picked]}
            allowPickType={[PickInputValueType.Model]}
            onPick={onPick}
            onFocus={() => setActive(2)}
            placeholder='请选择天线'
          />
        </CommandLabeledItemWrapper>
        <ComCommand
          label={''}
          isActive={active === 1}
          onFocus={() => setActive(1)}
          cmdRef={cmdRef.current}
          param={param}
          relyKey={'antPoint'}
          onRemove={() => remove()}
          onChange={(value, i) => {
            setParam((state) => {
              const newPoint = [
                ...(state.antPoint?.point || [0, 0, 0]),
              ] as Vector3Tuple;
              newPoint[i] = value;
              return {
                ...state,
                antPoint: {
                  ...state.antPoint,
                  point: newPoint,
                },
              };
            });
          }}
        />
        <CommandLabeledItemWrapper
          label='参考点'
          className='mt_10'>
          <MultiPickInput
            active={active === 3}
            value={[pickedPoint]}
            allowPickType={[PickInputValueType.Vertex]}
            onPick={(result) => setPickedPoint(result[0])}
            onFocus={() => setActive(3)}
            placeholder='参考点(默认初始原点)'
          />
        </CommandLabeledItemWrapper>
        <CommandLabeledItemWrapper
          label='参考系'
          className='mt_10'>
          <MultiPickInput
            active={active === 4}
            value={[pickedAxis]}
            allowPickType={[PickInputValueType.Frame]}
            onPick={(result) => setPickedAxis(result[0])}
            onFocus={() => setActive(4)}
            placeholder='参考系(默认初始轴系)'
          />
        </CommandLabeledItemWrapper>
      </div>
      <div className='w_full mt_10'>
        <CommandFormFooter
          isPreviewLoading={isPreviewLoading}
          isSubmitLoading={isLoading}
          onPreview={preview}
          showPreview
          onClose={onClose}
          onSubmit={checkAndFinishDraw}
          isSubmitDisabled={!isExecuted}
          isPreviewDisabled={!isExecuted}
        />
      </div>
    </CommandDialog>
  );
}

export const cmdElec: BaseCommand = {
  id: 'CmdElec',
  label: 'command.antennaPoint',
  icon: 'commands/elec/antenna-point',
  group: 'elec',
  create: function (label: string, onClose: () => void, props) {
    return (
      <PointAxis
        title={i18n.t(label)}
        onClose={onClose}
        props={props}
      />
    );
  },
};

function getId(picked, param) {
  const id = picked?.idInfo?.o;
  const antPoint: Vector3Tuple = param.antPoint?.point;
  const { x = 0, y = 0, z = 0, ox = 0, oy = 0, oz = 0 } = baseInfo;
  const startPoint: Vector3Tuple = [x, y, z];
  const originPoint: Vector3Tuple = [ox, oy, oz];
  return {
    id,
    antPoint,
    startPoint,
    originPoint,
  };
}
